from django.shortcuts import render

# Create your views here.
from django_redis import get_redis_connection
from rest_framework.response import Response
from rest_framework.views import APIView

from cart.serializers import CartSerializer, CartSKUSerializer, CartDeleteSerializer
import base64
import pickle

from goods.models import SKU


class CartView(APIView):
    """
    购物车 增删改查
    """

    def perform_authentication(self, request):
        """
        重写父类的用户验证方法,不在进入视图就检查JWT
        """
        pass

    def post(self, request):
        """
        增加商品到购物车中

        请求数据
        sku_id	    商品sku id
        count	    数量
        selected	是否勾选，默认勾选

        # 获取数据
        # 校验数据
        # 判断用户是否登陆
        # 增加到购物车
            # 用户登陆存在 redis中
            # 用户未登陆存在 cookie中
        # 返回响应
        :param request:
        :return:
        """

        # 获取数据 校验数据
        serializer = CartSerializer(data=request.data)
        try:
            serializer.is_valid(raise_exception=True)
        except Exception:
            print(serializer.error_messages)
            return Response(serializer.error_messages, 400)

        # 获取校验通过的数据
        sku_id = serializer.data.get('sku_id')
        count = serializer.data.get('count')
        selected = serializer.data.get('selected')

        # 判断用户是否登陆
        try:
            user = request.user
        except Exception:
            user = None

        # 增加到购物车

        if user and user.is_authenticated:
            # 如果用户存在 保存在redis中
            # 创建redis连接
            redis_conn = get_redis_connection('cart')
            # 保存数据
            redis_conn.hincrby('cart_%s' % user.id, sku_id, count)
            if selected:
                redis_conn.sadd('cart_selected_%s' % user.id, sku_id)
            # 返回响应
            return Response(serializer.data)
        else:
            # 如果用户不存在保存在cookie中
            # 从cookie中获取购物车信息
            cart = request.COOKIES.get('cart')
            if cart:
                # 存在 先解码
                cart_dict = pickle.loads(base64.b64decode(cart.encode()))
            else:
                cart_dict = {}

            # 如果存在 修改数量
            if sku_id in cart_dict:
                old_count = cart_dict[sku_id]['count']
                count += old_count

            cart_dict[sku_id] = {
                'count': count,
                'selected': selected
            }
            # 对内容编码返回
            resp = Response(serializer.data)
            cart_str = base64.b64encode(pickle.dumps(cart_dict)).decode()
            resp.set_cookie('cart', cart_str, 24 * 3600)
            return resp

    def get(self, request):
        """
        查询 购物车记录
        # 判断用户是否登陆
        # 登陆用户在redis中
        # 未登陆用户给在cookie中 获取数据
        # 根据商品id 获取商品信息
        # 返回响应

        :param request:
        :return:
        """

        # 判断用户是否登陆
        try:
            user = request.user
        except Exception:
            user = None

        if user and user.is_authenticated:
            # 登陆用户在redis中
            # 建立redis连接
            redis_conn = get_redis_connection('cart')
            # 获取数据
            redis_cart = redis_conn.hgetall('cart_%s' % user.id)
            redis_cart_selected = redis_conn.smembers('cart_selected_%s' % user.id)
            # 将数据转成 cookie 存数据的格式  cart = {商品id：{’count‘:1,’selected‘：bool},商品id：{’count‘:1,’selected‘：bool}}
            cart = {}
            for sku_id, count in redis_cart.items():
                cart[int(sku_id)] = {
                    'count': int(count),
                    'selected': sku_id in redis_cart_selected
                }

        else:
            # 未登陆用户给在cookie中 获取数据
            cart_str = request.COOKIES.get('cart')
            # 判断是否存在
            if cart_str:
                # 解码
                cart = pickle.loads(base64.b64decode(cart_str.encode()))
            else:
                cart = {}

        # 根据商品id 获取商品信息
        skus = SKU.objects.filter(id__in=cart.keys())
        # 给商品增加 数量 和选中属性
        for sku in skus:
            sku.count = cart[sku.id]['count']
            sku.selected = cart[sku.id]['selected']

        # 序列化 返回响应
        sku_serializer = CartSKUSerializer(skus, many=True)
        return Response(sku_serializer.data)

    def put(self, request):
        """
        修改 购物车 中的数量 和 勾选状态

        # 请求的数据
        sku_id count selected

        # 校验请求数据
        # 获取校验之后的数据
        # 获取用户信息
        # 用户存在 从redis中 修改
        # 用户不存在 从cookie中 修改
        :param request:
        :return:
        """

        # 校验请求数据
        serializer = CartSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        # 获取校验之后的数据
        sku_id = serializer.data.get('sku_id')
        count = serializer.data.get('count')
        selected = serializer.data.get('selected')
        # 获取用户信息
        try:
            user = request.user
        except Exception:
            user = None
        if user and user.is_authenticated:
            # 用户存在 从redis中 修改
            # 获取reids连接
            redis_conn = get_redis_connection('cart')
            # 更新数据
            redis_conn.hset('cart_%s' % user.id, sku_id, count)
            if selected:
                redis_conn.sadd('cart_selected_%s' % user.id, sku_id)
            else:
                redis_conn.srem('cart_selected_%s' % user.id, sku_id)

            return Response(serializer.data)
        else:
            # 用户不存在 从cookie中 修改
            cart_str = request.COOKIES.get('cart')
            if cart_str:
                cart = pickle.loads(base64.b64decode(cart_str.encode()))
            else:
                cart = {}
            # 修改商品信息
            cart[sku_id] = {
                'count': count,
                'selected': selected
            }
            # 编码 返回
            resp = Response(serializer.data)
            resp_cooke = base64.b64encode(pickle.dumps(cart)).decode()
            resp.set_cookie('cart', resp_cooke, 24 * 3600)
            return resp

    def delete(self, request):
        """
        购物车 删除

        请求参数
        sku_id

        # 获取请求数据 校验
        # 获取校验后的数据
        # 判断用户是否登陆
        # 用户存在 删除redis中的数据
        # 用户不存在 删除cookie中的数据
        # 返回响应

        :param request:
        :return:
        """

        # 获取请求数据 校验
        serializer = CartDeleteSerializer(data=request.data)
        serializer.is_valid()

        # 获取校验后的数据
        sku_id = serializer.data.get("sku_id")

        # 判断用户是否登陆
        try:
            user = request.user
        except Exception:
            user = None

        if user and user.is_authenticated:
            # 用户存在 删除redis中的数据
            # 建立redis 连接
            redis_conn = get_redis_connection('cart')
            # 删除数据
            redis_conn.hdel('cart_%s' % user.id, sku_id)
            redis_conn.srem('cart_selected_%s' % user.id, sku_id)
            return Response(serializer.data)
        else:
            # 用户不存在 删除cookie中的数据
            # 获取cookie中的数据
            cart_srt = request.COOKIES.get('cart')
            if cart_srt:
                # 解码
                cart_dict = pickle.loads(base64.b64decode(cart_srt.encode()))
            else:
                cart_dict = {}

            if sku_id in cart_dict:
                del cart_dict[sku_id]

            # 编码
            cart = base64.b64encode(pickle.dumps(cart_dict)).decode()
            resp = Response(serializer.data)
            resp.set_cookie('cart', cart)
            # 返回响应
            return resp
